package com.yj.forum.services.impl;

import com.yj.forum.common.AppResult;
import com.yj.forum.common.ResultCode;
import com.yj.forum.dao.UserMapper;
import com.yj.forum.exception.ApplicationException;
import com.yj.forum.model.User;
import com.yj.forum.services.IUserService;
import com.yj.forum.utils.MD5Util;
import com.yj.forum.utils.StringUtil;
import com.yj.forum.utils.UUIDUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;

@Service
@Slf4j
public class UserServiceImpl implements IUserService {
    @Resource
     private UserMapper userMapper;

    @Override
    public void createNormalUser(User user) {
        //非空校验
        if(user == null) {
            //打印日志
            log.error(ResultCode.ERROR_IS_NULL.toString());
            //抛出是空的异常
            throw new ApplicationException(AppResult.failed(ResultCode.ERROR_IS_NULL));
        }
        //必传参数
        if(StringUtil.isEmpty(user.getUsername())
        || StringUtil.isEmpty(user.getNickname())
        || StringUtil.isEmpty(user.getPassword())
        || StringUtil.isEmpty(user.getSalt())) {
            //打印日志
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            //抛出参数校验失败的异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //判断用户是否存在
        User existsUser = userMapper.selectByUserName(user.getUsername());
        if(existsUser != null) {
            //打印日志
            log.warn(ResultCode.FAILED_USER_EXISTS.toString());
            //抛出用户已存在的异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_EXISTS));
        }
        // 除了注册时传⼊的有效值，其他全部使⽤默认
        if(user.getGender() == null) {
            user.setGender((byte) 2);
        }
        user.setIsAdmin((byte) 0);
        user.setAvatarUrl(null);
        user.setArticleCount(0);
        user.setState((byte) 0);
        user.setDeleteState((byte) 0);
        Date date = new Date();
        user.setCreateTime(date);
        user.setUpdateTime(date);

        //插入数据库
        int row = userMapper.insertSelective(user);
        //插入成功校验
        if(row != 1) {
            //记录日志
            log.info(ResultCode.FAILED_CREATE.toString());
            //抛出新增失败异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_CREATE));
        }

        //成功新增用户
        log.info("新增⽤⼾成功：username = " + user.getUsername());
    }


    @Override
    public User selectByUserName(String username) {
        return userMapper.selectByUserName(username);
    }



    @Override
    public User login(String username, String password) {
        //非空校验
        if(StringUtil.isEmpty(username) || StringUtil.isEmpty(password)) {
            log.info(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //根据用户名查询用户
        User user = selectByUserName(username);
        //用户不存在
        if(user == null) {
            log.info(ResultCode.FAILED_USER_NOT_EXISTS.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS));
        }
        //校验密码
        //String cipherText = MD5Util.md5Salt(password, user.getSalt());
        //密码不正确
        if(!MD5Util.verifyOriginalAndCiphertext(password, user.getSalt(),user.getPassword())) {
            log.info(ResultCode.FAILED_LOGIN.toString() + " 密码错误：username = " + username );
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_LOGIN));
        }

        return user;
    }

    @Override
    public User selectById(long id) {
        return userMapper.selectByPrimaryKey(id);
    }

    @Override
    public void addOneArticleCountById(Long id) {
        //非空校验
        if( id == null || id <= 0) {
            log.warn(ResultCode.FAILED_USER_ARTICLE_COUNT.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_ARTICLE_COUNT));
        }
        //获取用户
        User user = userMapper.selectByPrimaryKey(id);
        if(user == null) {
            log.warn(ResultCode.ERROR_IS_NULL.toString() + " 查询到的用户不存在：id："+ id );
            throw new ApplicationException(AppResult.failed(ResultCode.ERROR_IS_NULL));
        }
        //更新用户发帖数
        User updateUser = new User();
        updateUser.setId(user.getId());
        updateUser.setArticleCount((user.getArticleCount() == null ? 1 : user.getArticleCount()) + 1);
        int row = userMapper.updateByPrimaryKeySelective(updateUser);
        //校验更新行数
        if(row != 1) {
            log.warn(ResultCode.FAILED.toString() + ", 受影响的⾏数不等于 1 .");
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED));
        }


    }
    /**
     * ⽤⼾发帖数 -1
     * @param id 版块Id
     */
    @Override
    public void subOneArticleCountById(Long id) {
        //非空校验
        if(id == null || id <= 0) {
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //调用dao 拿板块
        User user = userMapper.selectByPrimaryKey(id);
        //校验
        if(user == null) {
            log.warn(ResultCode.FAILED_USER_NOT_EXISTS.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS));
        }

        //构造更新对象
        User updateUser = new User();
        updateUser.setId(user.getId());
        updateUser.setArticleCount((user.getArticleCount() == null  || user.getArticleCount() == 0)? 0 : user.getArticleCount()-1);
        //调用dao，更新数据库
        int row = userMapper.updateByPrimaryKeySelective(updateUser);
        //校验
        if(row != 1) {
            log.error(ResultCode.ERROR_SERVICES.toString()+ ", 受影响的⾏数不等于 1 为 " + row);
            throw new ApplicationException(AppResult.failed(ResultCode.ERROR_SERVICES));
        }
    }
    /**
     * 修改个⼈信息
     * @param user 要更新的对象
     */
    @Override
    public void modifyInfo(User user) {
        //非空校验
        if(user == null || user.getId() == null || user.getId() <= 0) {
            log.warn(ResultCode.FAILED_USER_NOT_EXISTS.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS));
        }
        //校验⽤⼾是否存在
        User existsUser = userMapper.selectByPrimaryKey(user.getId());
        if(existsUser == null || existsUser.getDeleteState() != 0) {
            log.warn(ResultCode.FAILED_USER_NOT_EXISTS.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS));
        }
        //校验修改参数，使用标志位记录有修改参数吗，false代表没有
        boolean flag = false;
        //对每个⼀个参数进⾏校验并赋值
        User updateUser = new User();
        updateUser.setId(user.getId());
        //⽤⼾名
        if(!StringUtil.isEmpty(user.getUsername())) {
            //需要更新⽤⼾名(登录名)时，进⾏唯⼀性的校验
            User checkUser = userMapper.selectByUserName(user.getUsername());
            if(checkUser != null) {
                log.warn(ResultCode.FAILED_USER_EXISTS.toString());
                throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_EXISTS));
            }
            //没有 赋值
            updateUser.setUsername(user.getUsername());
            //更新标志位
            flag = true;
        }
        // 校验昵称
        if(!StringUtil.isEmpty(user.getNickname()) && !user.getNickname().equals(existsUser.getNickname())) {
            //设置昵称
            updateUser.setNickname(user.getNickname());
            //更新标志位
            flag = true;
        }
        //校验性别
        if(user.getGender() != null && !user.getGender().equals(existsUser.getGender())) {
            // 设置性别
            updateUser.setGender(user.getGender());
            // 合法性校验
            if (updateUser.getGender() > 2 || updateUser.getGender() < 0) {
                updateUser.setGender((byte) 2);
            }
            // 更新标志位
            flag = true;
        }
        //校验邮箱
        if(!StringUtil.isEmpty(user.getEmail()) && !user.getEmail().equals(existsUser.getEmail())) {
            //设置邮箱
            updateUser.setEmail(user.getEmail());
            //更新标志位
            flag = true;
        }
        //校验电话号码
        if(!StringUtil.isEmpty(user.getPhoneNum()) && !user.getPhoneNum().equals(existsUser.getPhoneNum())) {
            //设置电话号码
            updateUser.setPhoneNum(user.getPhoneNum());
            //更新标志位
            flag = true;
        }
        //校验个⼈简介
        if(!StringUtil.isEmpty(user.getRemark()) && !user.getRemark().equals(existsUser.getRemark())) {
            //设置个人简介
            updateUser.setRemark(user.getRemark());
            //更新标志位
            flag = true;
        }
        //根据标志位来决定是否可以执⾏更新
        if(!flag) {
            log.warn(ResultCode.FAILED_USER_UPDATE_INFO.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_UPDATE_INFO));
        }
        //调用dao
        int row = userMapper.updateByPrimaryKeySelective(updateUser);
        if(row != 1) {
            log.warn(ResultCode.FAILED.toString() + ", 受影响的⾏数不等于 1 .");
            throw new ApplicationException(AppResult.failed(ResultCode.ERROR_SERVICES));
        }


    }

    /**
     * 修改⽤⼾密码
     * @param id ⽤⼾Id
     * @param newPassword 新密码
     * @param oldPassword ⽼密码
     */
    @Override
    public void modifyPassword(Long id, String newPassword, String oldPassword) {
        //非空校验
        if(id == null || id <= 0 || StringUtil.isEmpty(newPassword) || StringUtil.isEmpty(oldPassword)) {
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //拿取用户
        User user = userMapper.selectByPrimaryKey(id);
        //校验
        if(user == null || user.getDeleteState() != 0) {
            log.warn(ResultCode.FAILED_USER_NOT_EXISTS.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS));
        }
        //校验老密码是否正确
        if(!MD5Util.verifyOriginalAndCiphertext(oldPassword, user.getSalt(), user.getPassword())) {
            log.info(ResultCode.FAILED.toString() + " 密码错误：username = " + user.getUsername() );
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED));
        }
        //修改密码
        User updateUser = new User();
        updateUser.setId(user.getId());
        updateUser.setSalt(UUIDUtil.UUID_32());
        updateUser.setPassword( MD5Util.md5Salt( newPassword, updateUser.getSalt() ) );
        updateUser.setUpdateTime(new Date());

        //更新
        int row = userMapper.updateByPrimaryKeySelective(updateUser);
        //校验
        if(row != 1) {
            log.error(ResultCode.ERROR_SERVICES.toString()+ ", 受影响的⾏数不等于 1 为 " + row);
            throw new ApplicationException(AppResult.failed(ResultCode.ERROR_SERVICES));
        }
        // 打印⽇志
        log.info("⽤⼾密码修改成功：" + user.getUsername());

    }
}
